import pyperclip
import re
import time
import tkinter as tk
from tkinter import ttk
import threading
import io
import win32clipboard
from PIL import Image

# ========== 功能1：LaTeX转换 ==========
def convert_latex_to_dollars(text):
    """将LaTeX数学环境格式转换为$...$和$$...$$"""
    if r'\\[' in text or r'\\]' in text or r'\\(' in text or r'\\)' in text:
        return text
    text = re.sub(r'\\\[\s*(.*?)\s*\\\]', r'$$\1$$', text)
    text = re.sub(r'\\\(\s*(.*?)\s*\\\)', r'$\1$', text)
    return text

def remove_think_tags(text):
    """移除所有<think>和</think>标签"""
    return re.sub(r'<\/think>|<think>', '', text)

def replace_escaped_asterisks(text):
    """将所有\*转换为*"""
    return re.sub(r'\\\*', '*', text)

def process_latex_clipboard(text):
    text = remove_think_tags(text)
    text = replace_escaped_asterisks(text)
    text = convert_latex_to_dollars(text)
    return text

# ========== 功能2：去掉思考内容 ==========
def remove_think_content(text):
    """只保留</think>或</thought>标签后的内容，并去除标签残留的半标签（如t>），如果没有则原样返回"""
    tag_pos = text.find("</think>")
    tag_len = len("</think>")
    if tag_pos == -1:
        tag_pos = text.find("</thought>")
        tag_len = len("</thought>")
    if tag_pos != -1:
        # 取标签后的内容
        result = text[tag_pos + tag_len:]
        # 去除开头可能残留的半标签如 t>、k>、nk>、hink>、ought> 等
        result = re.sub(r'^[a-zA-Z]{1,7}>', '', result.lstrip())
        return result.lstrip('\n\r ')
    return text

# ========== 功能3：检测剪切板内容类型 ==========
def is_image_in_clipboard():
    """检查剪切板是否包含图片"""
    try:
        win32clipboard.OpenClipboard()
        formats = []
        next_format = win32clipboard.EnumClipboardFormats(0)
        while next_format:
            formats.append(next_format)
            next_format = win32clipboard.EnumClipboardFormats(next_format)
        win32clipboard.CloseClipboard()
        
        # 常见的图片格式ID
        image_formats = [win32clipboard.CF_DIB, win32clipboard.CF_BITMAP, win32clipboard.CF_DIBV5]
        return any(fmt in formats for fmt in image_formats)
    except:
        return False

def is_file_in_clipboard():
    """检查剪切板是否包含文件"""
    try:
        win32clipboard.OpenClipboard()
        formats = []
        next_format = win32clipboard.EnumClipboardFormats(0)
        while next_format:
            formats.append(next_format)
            next_format = win32clipboard.EnumClipboardFormats(next_format)
        win32clipboard.CloseClipboard()
        
        # 文件拖放格式ID
        file_formats = [win32clipboard.CF_HDROP]
        # 检查是否有自定义的文件格式
        file_format_name = "FileNameW"
        try:
            file_format_id = win32clipboard.RegisterClipboardFormat(file_format_name)
            file_formats.append(file_format_id)
        except:
            pass
            
        return any(fmt in formats for fmt in file_formats)
    except:
        return False

# ========== 剪切板监控主流程 ==========
def monitor_clipboard(stop_event, use_think_remover, use_latex_converter, protect_images, protect_files, update_status):
    update_status("开始监视剪切板...")
    last_text = pyperclip.paste()
    try:
        while not stop_event.is_set():
            # 检查是否为图片或文件
            if (protect_images() and is_image_in_clipboard()):
                update_status("检测到图片，已跳过处理")
                time.sleep(0.5)  # 稍微延长检查间隔，避免频繁检查
                continue
                
            if (protect_files() and is_file_in_clipboard()):
                update_status("检测到文件，已跳过处理")
                time.sleep(0.5)  # 稍微延长检查间隔，避免频繁检查
                continue
            
            # 处理文本内容
            try:
                current_text = pyperclip.paste()
                processed_text = current_text
                changed = False
                
                if use_think_remover():
                    new_text = remove_think_content(processed_text)
                    if new_text != processed_text:
                        processed_text = new_text
                        changed = True
                        
                if use_latex_converter():
                    new_text = process_latex_clipboard(processed_text)
                    if new_text != processed_text:
                        processed_text = new_text
                        changed = True
                        
                if changed and processed_text != current_text:
                    pyperclip.copy(processed_text)
                    update_status("已处理并更新剪切板内容")
                    last_text = processed_text
                elif current_text != last_text:
                    update_status("剪切板已更新，无需处理")
                    last_text = current_text
            except:
                update_status("无法处理当前剪切板内容")
                
            time.sleep(0.1)
    except Exception as e:
        update_status(f"发生错误: {str(e)}")

# ========== GUI界面 ==========
def create_gui():
    root = tk.Tk()
    root.title("大模型输出的剪切板处理")
    root.geometry("350x280")

    stop_event = threading.Event()
    status_label = ttk.Label(root, text="准备就绪...", wraplength=320)
    status_label.pack(pady=10)

    # 勾选框变量
    think_var = tk.BooleanVar(value=True)
    latex_var = tk.BooleanVar(value=True)
    image_var = tk.BooleanVar(value=True)
    file_var = tk.BooleanVar(value=True)

    think_cb = ttk.Checkbutton(root, text="去掉思考内容（仅保留</think>后内容）", variable=think_var)
    think_cb.pack(anchor='w', padx=20)
    
    latex_cb = ttk.Checkbutton(root, text="LaTeX公式转换为美金符号", variable=latex_var)
    latex_cb.pack(anchor='w', padx=20)
    
    image_cb = ttk.Checkbutton(root, text="保护图片（复制图片时不处理）", variable=image_var)
    image_cb.pack(anchor='w', padx=20)
    
    file_cb = ttk.Checkbutton(root, text="保护文件（复制文件时不处理）", variable=file_var)
    file_cb.pack(anchor='w', padx=20)

    def update_status(text):
        status_label.config(text=text)

    def use_think_remover():
        return think_var.get()
        
    def use_latex_converter():
        return latex_var.get()
        
    def protect_images():
        return image_var.get()
        
    def protect_files():
        return file_var.get()

    def stop_monitoring():
        stop_event.set()
        root.quit()
        root.destroy()

    stop_button = ttk.Button(root, text="停止监视并退出", command=stop_monitoring)
    stop_button.pack(pady=15)

    monitor_thread = threading.Thread(
        target=monitor_clipboard,
        args=(stop_event, use_think_remover, use_latex_converter, protect_images, protect_files, update_status)
    )
    monitor_thread.daemon = True
    monitor_thread.start()

    root.mainloop()

if __name__ == "__main__":
    try:
        create_gui()
    except Exception as e:
        print(f"发生错误: {str(e)}")
        input("\n按回车键退出...") 